home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Python / structmember.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-10  |  5.1 KB  |  254 lines

  1. /* Map C struct members to Python object attributes */
  2.  
  3. #include "Python.h"
  4.  
  5. #include "structmember.h"
  6. #include "protos/structmember.h"
  7.  
  8. static PyObject *
  9. listmembers(mlist)
  10.     struct memberlist *mlist;
  11. {
  12.     int i, n;
  13.     PyObject *v;
  14.     for (n = 0; mlist[n].name != NULL; n++)
  15.         ;
  16.     v = PyList_New(n);
  17.     if (v != NULL) {
  18.         for (i = 0; i < n; i++)
  19.             PyList_SetItem(v, i,
  20.                        PyString_FromString(mlist[i].name));
  21.         if (PyErr_Occurred()) {
  22.             Py_DECREF(v);
  23.             v = NULL;
  24.         }
  25.         else {
  26.             PyList_Sort(v);
  27.         }
  28.     }
  29.     return v;
  30. }
  31.  
  32. PyObject *
  33. PyMember_Get(addr, mlist, name)
  34.     char *addr;
  35.     struct memberlist *mlist;
  36.     char *name;
  37. {
  38.     struct memberlist *l;
  39.     
  40.     if (strcmp(name, "__members__") == 0)
  41.         return listmembers(mlist);
  42.     for (l = mlist; l->name != NULL; l++) {
  43.         if (strcmp(l->name, name) == 0) {
  44.             PyObject *v;
  45.             addr += l->offset;
  46.             switch (l->type) {
  47.             case T_BYTE:
  48.                 v = PyInt_FromLong((long)
  49.                          (((*(char*)addr & 0xff)
  50.                            ^ 0x80) - 0x80));
  51.                 break;
  52.             case T_UBYTE:
  53.                 v = PyInt_FromLong((long) *(char*)addr & 0xff);
  54.                 break;
  55.             case T_SHORT:
  56.                 v = PyInt_FromLong((long) *(short*)addr);
  57.                 break;
  58.             case T_USHORT:
  59.                 v = PyInt_FromLong((long)
  60.                          *(unsigned short*)addr);
  61.                 break;
  62.             case T_INT:
  63.                 v = PyInt_FromLong((long) *(int*)addr);
  64.                 break;
  65.             case T_UINT:
  66.                 v = PyInt_FromLong((long)
  67.                            *(unsigned int*)addr);
  68.                 break;
  69.             case T_LONG:
  70.                 v = PyInt_FromLong(*(long*)addr);
  71.                 break;
  72.             case T_ULONG:
  73.                 v = PyLong_FromDouble((double)
  74.                            *(unsigned long*)addr);
  75.                 break;
  76.             case T_FLOAT:
  77.                 v = PyFloat_FromDouble((double)*(float*)addr);
  78.                 break;
  79.             case T_DOUBLE:
  80.                 v = PyFloat_FromDouble(*(double*)addr);
  81.                 break;
  82.             case T_STRING:
  83.                 if (*(char**)addr == NULL) {
  84.                     Py_INCREF(Py_None);
  85.                     v = Py_None;
  86.                 }
  87.                 else
  88.                     v = PyString_FromString(*(char**)addr);
  89.                 break;
  90.             case T_STRING_INPLACE:
  91.                 v = PyString_FromString((char*)addr);
  92.                 break;
  93. #ifdef macintosh
  94.             case T_PSTRING:
  95.                 if (*(char**)addr == NULL) {
  96.                     Py_INCREF(Py_None);
  97.                     v = Py_None;
  98.                 }
  99.                 else
  100.                     v = PyString_FromStringAndSize(
  101.                         (*(char**)addr)+1,
  102.                         **(unsigned char**)addr);
  103.                 break;
  104.             case T_PSTRING_INPLACE:
  105.                 v = PyString_FromStringAndSize(
  106.                     ((char*)addr)+1,
  107.                     *(unsigned char*)addr);
  108.                 break;
  109. #endif /* macintosh */
  110.             case T_CHAR:
  111.                 v = PyString_FromStringAndSize((char*)addr, 1);
  112.                 break;
  113.             case T_OBJECT:
  114.                 v = *(PyObject **)addr;
  115.                 if (v == NULL)
  116.                     v = Py_None;
  117.                 Py_INCREF(v);
  118.                 break;
  119.             default:
  120.                 PyErr_SetString(PyExc_SystemError,
  121.                         "bad memberlist type");
  122.                 v = NULL;
  123.             }
  124.             return v;
  125.         }
  126.     }
  127.     
  128.     PyErr_SetString(PyExc_AttributeError, name);
  129.     return NULL;
  130. }
  131.  
  132. int
  133. PyMember_Set(addr, mlist, name, v)
  134.     char *addr;
  135.     struct memberlist *mlist;
  136.     char *name;
  137.     PyObject *v;
  138. {
  139.     struct memberlist *l;
  140.     PyObject *oldv;
  141.     
  142.     for (l = mlist; l->name != NULL; l++) {
  143.         if (strcmp(l->name, name) == 0) {
  144. #ifdef macintosh
  145.             if (l->readonly || l->type == T_STRING ||
  146.                 l->type == T_PSTRING)
  147.             {
  148. #else
  149.             if (l->readonly || l->type == T_STRING ) {
  150. #endif /* macintosh */
  151.                 PyErr_SetString(PyExc_TypeError,
  152.                         "readonly attribute");
  153.                 return -1;
  154.             }
  155.             if (v == NULL && l->type != T_OBJECT) {
  156.                 PyErr_SetString(PyExc_TypeError,
  157.                   "can't delete numeric/char attribute");
  158.                 return -1;
  159.             }
  160.             addr += l->offset;
  161.             switch (l->type) {
  162.             case T_BYTE:
  163.             case T_UBYTE:
  164.                 if (!PyInt_Check(v)) {
  165.                     PyErr_BadArgument();
  166.                     return -1;
  167.                 }
  168.                 *(char*)addr = (char) PyInt_AsLong(v);
  169.                 break;
  170.             case T_SHORT:
  171.             case T_USHORT:
  172.                 if (!PyInt_Check(v)) {
  173.                     PyErr_BadArgument();
  174.                     return -1;
  175.                 }
  176.                 *(short*)addr = (short) PyInt_AsLong(v);
  177.                 break;
  178.             case T_UINT:
  179.             case T_INT:
  180.                 if (!PyInt_Check(v)) {
  181.                     PyErr_BadArgument();
  182.                     return -1;
  183.                 }
  184.                 *(int*)addr = (int) PyInt_AsLong(v);
  185.                 break;
  186.             case T_LONG:
  187.                 if (!PyInt_Check(v)) {
  188.                     PyErr_BadArgument();
  189.                     return -1;
  190.                 }
  191.                 *(long*)addr = PyInt_AsLong(v);
  192.                 break;
  193.             case T_ULONG:
  194.                 if (PyInt_Check(v))
  195.                     *(long*)addr = PyInt_AsLong(v);
  196.                 else if (PyLong_Check(v))
  197.                     *(long*)addr = PyLong_AsLong(v);
  198.                 else {
  199.                     PyErr_BadArgument();
  200.                     return -1;
  201.                 }
  202.                 break;
  203.             case T_FLOAT:
  204.                 if (PyInt_Check(v))
  205.                     *(float*)addr =
  206.                         (float) PyInt_AsLong(v);
  207.                 else if (PyFloat_Check(v))
  208.                     *(float*)addr =
  209.                         (float) PyFloat_AsDouble(v);
  210.                 else {
  211.                     PyErr_BadArgument();
  212.                     return -1;
  213.                 }
  214.                 break;
  215.             case T_DOUBLE:
  216.                 if (PyInt_Check(v))
  217.                     *(double*)addr =
  218.                         (double) PyInt_AsLong(v);
  219.                 else if (PyFloat_Check(v))
  220.                     *(double*)addr = PyFloat_AsDouble(v);
  221.                 else {
  222.                     PyErr_BadArgument();
  223.                     return -1;
  224.                 }
  225.                 break;
  226.             case T_OBJECT:
  227.                 Py_XINCREF(v);
  228.                 oldv = *(PyObject **)addr;
  229.                 *(PyObject **)addr = v;
  230.                 Py_XDECREF(oldv);
  231.                 break;
  232.             case T_CHAR:
  233.                 if (PyString_Check(v) &&
  234.                     PyString_Size(v) == 1) {
  235.                     *(char*)addr =
  236.                         PyString_AsString(v)[0];
  237.                 }
  238.                 else {
  239.                     PyErr_BadArgument();
  240.                     return -1;
  241.                 }
  242.             default:
  243.                 PyErr_SetString(PyExc_SystemError,
  244.                         "bad memberlist type");
  245.                 return -1;
  246.             }
  247.             return 0;
  248.         }
  249.     }
  250.     
  251.     PyErr_SetString(PyExc_AttributeError, name);
  252.     return -1;
  253. }
  254.